package fr.unice.guitartools.recorder;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.GregorianCalendar;

import android.app.Activity;
import android.graphics.drawable.StateListDrawable;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import android.os.Bundle;
import android.os.SystemClock;
import android.text.format.DateFormat;
import android.text.method.DateTimeKeyListener;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Chronometer;
import android.widget.ImageButton;
import android.widget.Toast;

import fr.unice.guitartools.R;

public class AudioRecorderActivity extends Activity{
    int bufferSize;
	String fileName = "/sdcard/Sounds/Mic";
	int sampleRate;
	ImageButton buttonRec = null;
	ImageButton imageMicro = null;
	ImageButton buttonStopRec = null;
    Chronometer recChronometer;
    AudioRecorderThread recorder;

    public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// init recorder with bufferSize, and create a new Recorder
		sampleRate = 22050;
		InitComponents();
        bufferSize = AudioRecord.getMinBufferSize(sampleRate,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);
          }
    
private void InitComponents(){
	setContentView(R.layout.recorder);
StateListDrawable bgImageMicro = new StateListDrawable();
((ImageButton)findViewById(R.id.micro)).setBackgroundDrawable(bgImageMicro);
((ImageButton)findViewById(R.id.buttonRec)).setBackgroundDrawable(bgImageMicro);
((ImageButton)findViewById(R.id.buttonStopRec)).setBackgroundDrawable(bgImageMicro);

	recChronometer = (Chronometer) findViewById(R.id.chronometer);
    imageMicro = (ImageButton)findViewById(R.id.micro);
    buttonRec = (ImageButton) findViewById(R.id.buttonRec);
    buttonStopRec = (ImageButton) findViewById(R.id.buttonStopRec) ;
    buttonRec.setImageResource(R.drawable.record);
	buttonStopRec.setImageResource(R.drawable.stop_rec_disabled);
	imageMicro.setImageResource(R.drawable.micro_stoped);
	buttonRec.setOnClickListener(onRecorderListener);
	buttonStopRec.setOnClickListener(onStopRecordListener);
}

	private OnClickListener onRecorderListener = new OnClickListener() {
		public void onClick(View sender) {
			buttonRec.setImageResource(R.drawable.record_disabled);
			imageMicro.setImageResource(R.drawable.micro_play);
			buttonStopRec.setImageResource(R.drawable.stop_rec);
			buttonRec.setEnabled(false);
			buttonStopRec.setEnabled(true);
			onRec();
		}
	};
	
	private OnClickListener onStopRecordListener = new OnClickListener() {
		public void onClick(View sender) {
			buttonStopRec.setEnabled(false);
			buttonStopRec.setImageResource(R.drawable.stop_rec_disabled);
			imageMicro.setImageResource(R.drawable.micro_stoped);
			onStopRec();
			buttonRec.setEnabled(true);
			buttonRec.setImageResource(R.drawable.record);
		}
	};
	
	
	
	/**
	 * onRec() allows to start and stop record
	 * in thread we write audio date in a file
	 */
	private void onRec() {
			recChronometer.setFormat(null);
			recChronometer.setBase(SystemClock.elapsedRealtime());
			recChronometer.start();
           Log.d("Recorder", "Start Recording");
			buttonRec.setTag(R.string.button_tuning);
			buttonRec.setId(R.string.button_tuning);
			recorder = new AudioRecorderThread(
					AudioSource.MIC,sampleRate,AudioFormat.CHANNEL_IN_MONO, 
					AudioFormat.ENCODING_PCM_16BIT, bufferSize * 2,fileName);
			recorder.start();
	}
	
	private void onStopRec() {
		recChronometer.stop();
		Log.d("Recorder", "Stop Recording");
		recorder.StopRecording();
		String newfileName = fileName + DateFormat.format("_yyMMdd_hhmmss", new Date()) + ".wav";
		copyWaveFile(fileName + ".tmp", newfileName, bufferSize);
		Toast.makeText(this, "Record saved : " + newfileName, Toast.LENGTH_LONG).show();
		Log.d("Recorder", "File saved");
	}
	
	
	
	/**
	 * copyWaveFile 
	 * @param inFilename
	 * @param outFilename
	 * @param inBufferSize
	 */
	private void copyWaveFile(String inFilename,String outFilename, int inBufferSize){
		FileInputStream in = null;
		FileOutputStream out = null;
		long totalAudioLen = 0;
		long totalDataLen = totalAudioLen + 36;
		int channels = 1;
		long byteRate = 16 * sampleRate * channels/8;
		
		byte[] data = new byte[inBufferSize];
                
		try {
			in = new FileInputStream(inFilename);
			out = new FileOutputStream(outFilename);
			totalAudioLen = in.getChannel().size();
			totalDataLen = totalAudioLen + 36;
			
			Log.d("Recorder","File size: " + totalDataLen);
			
			WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
					sampleRate, channels, byteRate);
			
			while(in.read(data) != -1){
				out.write(data);
			}
			
			in.close();
			out.close();
			File f = new File(inFilename);
			f.delete();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void WriteWaveFileHeader(
			FileOutputStream out, long totalAudioLen,
			long totalDataLen, long longSampleRate, int channels,
			long byteRate) throws IOException {
		
		byte[] header = new byte[44];
		
		header[0] = 'R';  // RIFF/WAVE header
		header[1] = 'I';
		header[2] = 'F';
		header[3] = 'F';
		header[4] = (byte) (totalDataLen & 0xff);
		header[5] = (byte) ((totalDataLen >> 8) & 0xff);
		header[6] = (byte) ((totalDataLen >> 16) & 0xff);
		header[7] = (byte) ((totalDataLen >> 24) & 0xff);
		header[8] = 'W';
		header[9] = 'A';
		header[10] = 'V';
		header[11] = 'E';
		header[12] = 'f';  // 'fmt ' chunk
		header[13] = 'm';
		header[14] = 't';
		header[15] = ' ';
		header[16] = 16;  // 4 bytes: size of 'fmt ' chunk
		header[17] = 0;
		header[18] = 0;
		header[19] = 0;
		header[20] = 1;  // format = 1
		header[21] = 0;
		header[22] = (byte) channels;
		header[23] = 0;
		header[24] = (byte) (longSampleRate & 0xff);
		header[25] = (byte) ((longSampleRate >> 8) & 0xff);
		header[26] = (byte) ((longSampleRate >> 16) & 0xff);
		header[27] = (byte) ((longSampleRate >> 24) & 0xff);
		header[28] = (byte) (byteRate & 0xff);
		header[29] = (byte) ((byteRate >> 8) & 0xff);
		header[30] = (byte) ((byteRate >> 16) & 0xff);
		header[31] = (byte) ((byteRate >> 24) & 0xff);
		header[32] = (byte) (2 * 16 / 8);  // block align
		header[33] = 0;
		header[34] = 16;  // bits per sample
		header[35] = 0;
		header[36] = 'd';
		header[37] = 'a';
		header[38] = 't';
		header[39] = 'a';
		header[40] = (byte) (totalAudioLen & 0xff);
		header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
		header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
		header[43] = (byte) ((totalAudioLen >> 24) & 0xff);

		out.write(header, 0, 44);
	}
}
